package com.xuan.meihua.utils;

import com.nlf.calendar.Lunar;
import com.nlf.calendar.Solar;

import java.util.*;

/**
 * 干支转换工具
 */
public class GanZhiUtil {

    /**
     * 二十四小时对应十二地支
     */
    public static final Map<Integer, String> HOUR_ZHI = new HashMap<Integer, String>() {
        private static final long serialVersionUID = -1;

        {
            put(0, "子");  // 子
            put(1, "丑");  // 丑
            put(2, "丑");  // 丑
            put(3, "寅");  // 寅
            put(4, "寅");  // 寅
            put(5, "卯");  // 卯
            put(6, "卯");  // 卯
            put(7, "辰");  // 辰
            put(8, "辰");  // 辰
            put(9, "巳");  // 巳
            put(10, "巳"); // 巳
            put(11, "午"); // 午
            put(12, "午"); // 午
            put(13, "未"); // 未
            put(14, "未"); // 未
            put(15, "申"); // 申
            put(16, "申"); // 申
            put(17, "酉"); // 酉
            put(18, "酉"); // 酉
            put(19, "戌"); // 戌
            put(20, "戌"); // 戌
            put(21, "亥"); // 亥
            put(22, "亥"); // 亥
            put(23, "子"); // 子
        }

    };

//====================================================================================================================================================

    /**
     * 日期转干支（年柱：以立春当天作为新年的开始。月柱：以节交接时刻起算。日柱：根据流派判断。时柱：支持早子时和晚子时。）
     *
     * @param date     日期
     * @param dateType 日期类型（0:公历，1:农历）
     * @param liuPai   流派（0:晚子时日柱算当天，1:晚子时日柱算明天）
     * @return 干支
     */
    public static List<String> dateToGanZhi(Date date, int dateType, int liuPai) {

        // 1、初始化日期（通过公历日期初始化）
        Lunar lunar = new Lunar(date);

        // 2、通过农历日期计算
        if (dateType == 1) {
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            int year = c.get(Calendar.YEAR); // 年
            int month = c.get(Calendar.MONTH) + 1; // 月
            int day = c.get(Calendar.DATE); // 日
            int hour = c.get(Calendar.HOUR_OF_DAY); // 时
            int minute = c.get(Calendar.MINUTE); // 分
            int second = c.get(Calendar.SECOND); // 秒
            lunar = new Lunar(year, month, day, hour, minute, second);
        }

        // 3、计算四柱
        String yearZhu = lunar.getYearInGanZhiByLiChun(); // 年柱（以立春当天作为新年的开始）
        String monthZhu = lunar.getMonthInGanZhiExact(); // 月柱（以节交接时刻起算）
        String dayZhu = null; // 日柱
        String hourZhu = lunar.getTimeInGanZhi(); // 时柱（支持早子时和晚子时）

        // 4、判断流派
        if (liuPai != 0 && liuPai != 1) liuPai = 1;
        if (liuPai == 0) dayZhu = lunar.getDayInGanZhiExact2(); // 日柱（晚子时日柱算当天）
        if (liuPai == 1) dayZhu = lunar.getDayInGanZhiExact(); // 日柱（晚子时日柱算明天）

        // 5、返回干支
        return Arrays.asList(yearZhu, monthZhu, dayZhu, hourZhu);

    }

    /**
     * 干支转日期
     *
     * @param yearZhu   年柱
     * @param monthZhu  月柱
     * @param dayZhu    日柱
     * @param hourZhu   时柱
     * @param liuPai    流派（0:晚子时日柱算当天，1:晚子时日柱算明天）
     * @param beginYear 起始年份（从起始年份~至今的所有匹配日期）
     * @return 日期
     */
    public static List<List<String>> ganZhiToDate(String yearZhu, String monthZhu, String dayZhu, String hourZhu, int liuPai, int beginYear) {

        // 1、通过八字获取阳历列表
        List<Solar> solars = Solar.fromBaZi(yearZhu, monthZhu, dayZhu, hourZhu, liuPai, beginYear);

        // 2、遍历日期
        List<List<String>> list = new ArrayList<>();
        for (int i = 0; i < solars.size(); i++) {
            List<String> solarList = new ArrayList<>();
            Solar solar = solars.get(i); // 每一个公历日期
            String lunar = getLunarStr(new Lunar(solar)); // 每一个农历日期
            solarList.add(0, solar.toYmdHms()); // 公历日期
            solarList.add(1, lunar); // 农历日期
            list.add(i, solarList);
        }

        return list;

    }

//----------------------------------------------------------------------------------------------------------------------------------------------------

    /**
     * 获取公历日期字符串
     *
     * @param lunar 农历日期
     * @return 公历日期字符串
     */
    private static String getSolarStr(Lunar lunar) {

        Solar solar = lunar.getSolar();

        return (solar.getYear() + "年" + solar.getMonth() + "月" + solar.getDay() + "日" + solar.getHour() + "时" + solar.getMinute() + "分" + solar.getSecond() + "秒");

    }

    /**
     * 获取农历日期字符串
     *
     * @param lunar 农历日期
     * @return 农历日期字符串
     */
    private static String getLunarStr(Lunar lunar) {

        // 获取小时
        int hour = lunar.getHour();

        String lunarStr;

        // 判断时辰
        if (hour >= 23 || hour < 1) {
            // 判断早晚子时
            if (hour >= 23) {
                lunarStr = lunar + "(晚)子时";
            } else {
                lunarStr = lunar + "(早)子时";
            }
        } else {
            lunarStr = lunar + HOUR_ZHI.get(hour) + "时";
        }

        return lunarStr;

    }


}
